package common;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.net.Socket;

public class SendFile extends CommonFile{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private OutputStream m_dataOutputStream;
//	private ObjectOutputStream m_controlOutputStream;
//	private ObjectInputStream m_controlInputStream;
//	private File m_File;
//	private Socket m_dataSocket;
//	private Socket m_controlSocket;
	private String m_sFileToSend;

	public SendFile( File sendfile, Socket dataSocket, Socket controlSocket ) {
		// TODO Auto-generated constructor stub
		this.m_File = sendfile;
		this.m_dataSocket = dataSocket;
		this.m_controlSocket = controlSocket;
		try {
			m_controlOutputStream = new ObjectOutputStream( m_controlSocket.getOutputStream() );
			m_controlInputStream = new ObjectInputStream( m_controlSocket.getInputStream() );
			m_dataOutputStream = m_dataSocket.getOutputStream();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void setM_sFileToSend(String mSFileToSend) {
		m_sFileToSend = mSFileToSend;
	}

	//Reçoit un string sur le canal de controle
	String receiveText()
	{
		String sRet ="";
		try {
			sRet = m_controlInputStream.readUTF();
			System.out.println("SendFile::receiveText : " + sRet );
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return sRet;
	}
	
	//Envoie un string sur le canal de controle
	void sendText(String sTextToSend)
	{
		String sRet ="";
		try {
			System.out.println("SendFile::sendText : " +  sTextToSend);
			m_controlOutputStream.writeUTF(sTextToSend);
			m_controlOutputStream.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//Recoit un long sur le canal de controle
	long receiveLong()
	{
		long lRet = 0;
		try {
			lRet = m_controlInputStream.readLong();
			System.out.println("SendFile::receiveLong : " + lRet );
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return lRet;
	}
	
	//Recoit un long sur le canal de controle
	void sendLong(long longToSend )
	{
		try {
			m_controlOutputStream.writeLong(longToSend );
			m_controlOutputStream.flush();
			System.out.println("SendFile::sendLong : " + longToSend );
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	
	public boolean envoieFichier() throws IOException {
		String sControl = "";
		if (m_File.exists()) {
			sendText("OK");  // Envoie au receiver l'information que le fichier exist
			sControl =receiveText(); // on attend que le receiver soit pret
			if (sControl.equalsIgnoreCase("READY")) { 
				long taillefichier = m_File.length();
				long nbpassagesupose = taillefichier / 4096; // On envoie le fichier par paquet de 4096 Bytes.
				
				sendLong(taillefichier); // Envoie de la taille du fichier.
				
				InputStream inFile = new BufferedInputStream(new FileInputStream(m_File));
				ByteArrayOutputStream tableaubytes = new ByteArrayOutputStream();
				BufferedOutputStream tampon = new BufferedOutputStream(tableaubytes);

				int lu = inFile.read();
				int[] aecrire = new int[4096];
				int compteur = 0;
				long ouonestrendu = 0;
				sControl = receiveText(); // on attend que le receiver est démarré
				if (sControl.equalsIgnoreCase("START")) {
				// Tant qu'on est pas à la fin fichier
				while (lu > -1) {
					// On lit les données du fichier
					aecrire[compteur] = lu;
					lu = inFile.read();
					compteur++;
					// Quand on a rempli le tableau, on envoie un paquet de 4096 octets
					if (compteur == 4096) {
						compteur = 0;
						ouonestrendu++;
						// On remplit le tampon
						for (int x = 0; x < 4096; x++)
							tampon.write(aecrire[x]);

						// Et on l'envoie
						m_dataOutputStream.write(tableaubytes.toByteArray());

						tableaubytes.reset();
						System.out.println("Avancement : "
								+ (float) ouonestrendu / nbpassagesupose * 100
								+ "%");
					}
				}

				// On envoie le dernier paquet, qui ne fait pas forcément 4096
				// octets
				// On remplit le tampon
				for (int x = 0; x < 4096; x++)
					tampon.write(aecrire[x]);

				// Et on l'envoie
				tampon.flush();
				m_dataOutputStream.write(tableaubytes.toByteArray());
				m_dataOutputStream.flush();

				System.out.println("Avancement: " + (float) ouonestrendu
						/ nbpassagesupose * 100 + "%");

				inFile.close();
				tampon.close();
				System.out.println("Passages effectués : " + ouonestrendu);
				}
			}
			
		}
		else {
			sendText("NOK");
			}
		return true;
	}
}
